﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Windows.Forms;
using WFL.Windows;

namespace WFL.Demo.WinForm
{
    public class RichTextBoxEx : RichTextBox
    {
        private IRichEditOle _richEditOle;

        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);

            if (!DesignMode)
            {
                IntPtr ptr = IntPtr.Zero;
                if (API.User32.SendMessage(this.Handle, Header.Winuser.EM_GETOLEINTERFACE, IntPtr.Zero, ref ptr) == IntPtr.Zero)
                {
                    throw new Exception("IRichEditOle");
                }
                _richEditOle = (IRichEditOle)Marshal.GetObjectForIUnknown(ptr);
                Marshal.Release(ptr);
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_richEditOle != null)
                {
                    int result=Marshal.ReleaseComObject(_richEditOle);
                    _richEditOle = null;
                }
            }
            base.Dispose(disposing);
        }

        public void InsertImage(Image image)
        {
            if (image == null)
            {
                return;
            }
            PictureBox pictureBox = new PictureBox();
            pictureBox.Image = image;
            pictureBox.BackColor = BackColor;
            pictureBox.SizeMode = PictureBoxSizeMode.AutoSize;
            InsertControl(pictureBox);
        }

        public void InsertControl(Control control)
        {
            if (control == null)
            {
                return;
            }
            ILockBytes lockBytes = null;
            IStorage storage = null;
            IOleClientSite oleClientSite = null;
            try
            {
                lockBytes = API.Ole32.CreateILockBytesOnHGlobal(IntPtr.Zero, true);
                storage = API.Ole32.StgCreateDocfileOnILockBytes(lockBytes
                    , Header.ObjBase.STGM_SHARE_EXCLUSIVE | Header.ObjBase.STGM_CREATE | Header.ObjBase.STGM_READWRITE
                    , 0);
                int result = _richEditOle.GetClientSite(out oleClientSite);
                if (result != 0)
                {
                    Marshal.ThrowExceptionForHR(result);
                }
                REOBJECT reobject = new REOBJECT();
                reobject.cp = TextLength;
                reobject.clsid = Marshal.GenerateGuidForType(control.GetType());
                reobject.pstg = storage;
                reobject.poleobj = Marshal.GetIUnknownForObject(control);
                reobject.polesite = oleClientSite;
                reobject.dvAspect = DVASPECT.DVASPECT_CONTENT;
                reobject.dwFlags = Header.Richole.REO_BELOWBASELINE;
                reobject.dwUser = 1;
                if (_richEditOle.InsertObject(reobject) != 0)
                {
                    throw new Exception("InsertObject");
                }
            }
            finally
            {
                if (lockBytes != null)
                {
                    Marshal.ReleaseComObject(lockBytes);
                }
                if (storage != null)
                {
                    Marshal.ReleaseComObject(storage);
                }
                if (oleClientSite != null)
                {
                    Marshal.ReleaseComObject(oleClientSite);
                }
            }
        }
    }
}
